#include "tutorialBranchesSelection.hxx"
#include "tutorialSelection.hxx"
#include "baseSelection.hxx"
#include "CutUtils.hxx"
#include "Parameters.hxx"
#include "SubDetId.hxx"

//*******************************************************************************
tutorialBranchesSelection::tutorialBranchesSelection(bool forceBreak): SelectionBase(forceBreak){
//*******************************************************************************

    //Define the steps.
    DefineSteps();
}

//*******************************************************************************
void tutorialBranchesSelection::DefineSteps(){
//*******************************************************************************

    // Copy all steps from the tutorialSelection
    tutorialSelection tut;
    CopySteps(tut);

    // Add an action to the trunk
    AddStep(StepBase::kAction, "find long tpc tracks", new  FindLongTPCTracks());

    //Add a split to the trunk with 4 branches.
    AddSplit(4);

    //First branch is for 1-track events. We add now a cut to branch 0
    AddStep(0, StepBase::kCut, "1-track", new  OneTPCTrackCut());

    //Second branch is for 2-track events. We add now a cut to branch 1
    AddStep(1, StepBase::kCut, "2-tracks", new TwoTPCTracksCut());

    //Third branch is for >2 track events. We add now a cut to branch 2
    AddStep(2, StepBase::kCut, ">2-tracks", new MoreThanTwoTPCTracksCut());

    //Forth branch is for >2 track events in which the two tracks have more than 65 nodes. We add now a cut to branch 3
    AddStep(3, StepBase::kCut, ">2 long-tracks", new MoreThanTwoLongTPCTracksCut());


    // Set the branch aliases to the three branches (this is mandatory)
    // First integer is the branch number at each split. Since we have only one explit there is a single number (0, 1, 2)
    // Second integer is the alias number (0, 1, 2) to be used in the DrawingTools when refering to a specific branch   
    SetBranchAlias(0,"1-track",       0);
    SetBranchAlias(1,"2-tracks",      1);
    SetBranchAlias(2,">2-tracks",     2);
    SetBranchAlias(3,">2 long-tracks",3);
}

//********************************************************************
bool tutorialBranchesSelection::FillEventSummary(const AnaBoxB& box, AnaEventB& event, Int_t allCutsPassed[]){
//********************************************************************

    (void)box;
    //CC0pi
    if(allCutsPassed[0]){
        event.Summary->EventSample = nd280Samples::kFGD1NuMuCC0Pi;
    }  
    //CC1pi
    else if (allCutsPassed[1]){
        event.Summary->EventSample = nd280Samples::kFGD1NuMuCC1Pi;
    }
    //CCOther
    else if (allCutsPassed[2]){
        event.Summary->EventSample = nd280Samples::kFGD1NuMuCCOther;
    }

    // otherwise kUnassigned is used from the EventSummary constructor
    return (event.Summary->EventSample != nd280Samples::kUnassigned);
}


//*********************************************************************
bool FillSummaryAction_tutorialBranches::Apply(const AnaEventB& event, AnaBoxB& box) const{
//*********************************************************************

    if(!box.HMNtrack) return 1;

    event.Summary->LeptonCandidate[nd280Samples::kFGD1NuMuCC0Pi] = box.HMNtrack;
    event.Summary->LeptonCandidate[nd280Samples::kFGD1NuMuCC1Pi] = box.HMNtrack;
    event.Summary->LeptonCandidate[nd280Samples::kFGD1NuMuCCOther] = box.HMNtrack;

    for(int i = 0; i < 4; ++i){
        event.Summary->VertexPosition[nd280Samples::kFGD1NuMuCC0Pi][i] = box.HMNtrack->PositionStart[i];
        event.Summary->VertexPosition[nd280Samples::kFGD1NuMuCC1Pi][i] = box.HMNtrack->PositionStart[i];
        event.Summary->VertexPosition[nd280Samples::kFGD1NuMuCCOther][i] = box.HMNtrack->PositionStart[i];
    }
    if(box.HMNtrack->TrueTrack){
        event.Summary->TrueVertex[nd280Samples::kFGD1NuMuCC0Pi] = box.HMNtrack->TrueTrack->TrueVertex;
        event.Summary->TrueVertex[nd280Samples::kFGD1NuMuCC1Pi] = box.HMNtrack->TrueTrack->TrueVertex;
        event.Summary->TrueVertex[nd280Samples::kFGD1NuMuCCOther] = box.HMNtrack->TrueTrack->TrueVertex;
    }

    return 1;
}

//*********************************************************************
bool OneTPCTrackCut::Apply(const AnaEventB& event, AnaBoxB& box) const{
//*********************************************************************

    (void)event;

    if (box.nNegativeTPCtracks+box.nPositiveTPCtracks==1)
      return true;
    else
      return false; 
}


//*********************************************************************
bool TwoTPCTracksCut::Apply(const AnaEventB& event, AnaBoxB& box) const{
//*********************************************************************

    (void)event;

    if (box.nNegativeTPCtracks+box.nPositiveTPCtracks==2)
      return true;
    else
      return false; 
}


//*********************************************************************
bool MoreThanTwoTPCTracksCut::Apply(const AnaEventB& event, AnaBoxB& box) const{
//*********************************************************************

    (void)event;

    if (box.nNegativeTPCtracks+box.nPositiveTPCtracks>2)
      return true;
    else
      return false; 
}

//*********************************************************************
bool MoreThanTwoLongTPCTracksCut::Apply(const AnaEventB& event, AnaBoxB& box) const{
//*********************************************************************

    (void)event;

    // Cast the box such that we can access nLongTPCTracks, not present in AnaBoxB
    AnaBoxTutorial* tutBox = static_cast<AnaBoxTutorial*>(&box);

    if (tutBox->nLongTPCTracks>2)
      return true;
    else
      return false; 
}

//*********************************************************************
bool FindLongTPCTracks::Apply(const AnaEventB& event, AnaBoxB& box) const{
//*********************************************************************

  // Get all tracks using the TPC
  AnaTrackB* selTracks[NMAXTRACKS];
  int nTPC = anaUtils::GetAllTracksUsingTPC(event, selTracks);
  
  // Cast the box such that we can access nLongTPCTracks, not present in AnaBoxB
  AnaBoxTutorial* tutBox = static_cast<AnaBoxTutorial*>(&box);

  // reset to 0 
  tutBox->nLongTPCTracks=0;

  //loop over tpc tracks
  for (Int_t i=0;i<nTPC; ++i){
    AnaTrackB* track = selTracks[i];
    
    // Apply the fiducial cut
    if (!cutUtils::FiducialCut(*track, SubDetId::kFGD1)){
      continue;
    }
    
    // Gets the longest segment in the closest TPC
    AnaSubTrackB* TPCSegment = anaUtils::GetSegmentWithMostNodesInClosestTpc(*track);

    // Apply the nodes cut
    if (TPCSegment->NNodes>65) tutBox->nLongTPCTracks++;
  }  

  return true;
}


